/*
 * @Descripttion:
 * @Author: yubo
 * @Date: 2022-09-29 17:53:02
 * @LastEditTime: 2022-10-11 16:17:55
 */
#pragma once

#include <openssl/aes.h>

#include "base64.h"

#include <string.h>
#include <string>

//#define AES_BLOCK_SIZE 16


static AES_KEY encryptKey;
static void GenerateEncryptKey()
{
    if (encryptKey.rounds == 0)
    {
        AES_set_encrypt_key((const unsigned char *)AES_DEFAULT_KEY, 128, &encryptKey);
    }
}

static AES_KEY &GenerateDecryptKey()
{
    static AES_KEY decrptKey;
    AES_set_decrypt_key((const unsigned char *)AES_DEFAULT_KEY, 128, &decrptKey);
    return decrptKey;
}

void Check(const std::string& src)
{
    std::string tmp = base64_decode(src);

    auto &aeskey = GenerateDecryptKey();

    unsigned char out[65]{};
    //AES_decrypt((const unsigned char *)tmp.data(), out, &aeskey);

    unsigned char iv[AES_KEY_LENGTH] = { 10, 4, 117, 110, 100, 11, 5, 11, 7, 36, 98, 25, 15, 11, 7, 10 };
    AES_cbc_encrypt((const unsigned char*)tmp.data(), out, sizeof(out), &aeskey, iv, AES_DECRYPT);

    printf("decrpyted : %s\n", (const char *)out);
}

std::string Encrypt(const char *src)
{
    GenerateEncryptKey();

    /*
    int nDestSize = strlen(src);
    int newsize = (nDestSize + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE;

    int count = newsize / AES_BLOCK_SIZE;
    int modsize = newsize % AES_BLOCK_SIZE;

    char temp[4096]{};
    for (int i = 0; i < count; i++)
    {
        AES_encrypt((const unsigned char *)src + i * AES_BLOCK_SIZE, (unsigned char *)temp + i * AES_BLOCK_SIZE, &encryptKey);
    }

    if (modsize != 0)
    {
        unsigned char tempEx[AES_BLOCK_SIZE];

        ::memcpy(tempEx, src + count * AES_BLOCK_SIZE, modsize);
        AES_encrypt((const unsigned char *)tempEx, (unsigned char *)temp + count * AES_BLOCK_SIZE, &encryptKey);
    }
    */

    char temp[32]{};
    //AES_encrypt((const unsigned char *)src, (unsigned char *)temp, &encryptKey);

    unsigned char iv[AES_KEY_LENGTH] = { 10, 4, 117, 110, 100, 11, 5, 11, 7, 36, 98, 25, 15, 11, 7, 10 };
    AES_cbc_encrypt((const unsigned char *)src, (unsigned char *)temp, sizeof(temp), &encryptKey, iv, AES_ENCRYPT);

    std::string outBuff = base64_encode(temp);

    Check(outBuff);

    return outBuff;
}